package com.lg.meng.observable.download;


import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;

import com.blankj.utilcode.util.EncryptUtils;
import com.blankj.utilcode.util.LogUtils;
import com.lg.meng.application.StubApplication;
import com.lg.meng.model.ResponseVersionData;
import com.lg.meng.observable.BaseObservable;

import java.io.File;
import java.util.HashMap;
import java.util.Map;


/**
 * Author: Ligang
 * Date: 2019/5/2
 * Description: 下载管理：下载路径：app的包名/download
 */

public class VersionDownloaderManager extends BaseObservable<DownloadObserver> implements DownloadObserver {

    private Map<String, FileDownloader> downloaderMap = new HashMap<>();
    private static VersionDownloaderManager instance;

    private VersionDownloaderManager() {

    }

    public static VersionDownloaderManager getInstance() {
        if (instance == null) {
            synchronized (VersionDownloaderManager.class) {
                if (instance == null) {
                    instance = new VersionDownloaderManager();
                }
            }
        }
        return instance;
    }

    private FileDownloader getFileDownloader(String downloadType) {
        FileDownloader downloader = downloaderMap.get(downloadType);
        if (downloader == null) {
            downloader = new FileDownloader(downloadType);
            downloaderMap.put(downloadType, downloader);
        }
        return downloader;
    }

    public String buildFilePath(ResponseVersionData versionData) {
        String updateUrl = versionData.getUpdateUrl();
        if (!TextUtils.isEmpty(updateUrl)) {
            String DOWNLOAD_DIR;
            String fileName = updateUrl.substring(updateUrl.lastIndexOf("/") + 1);
            if (ContextCompat.checkSelfPermission(StubApplication.getApplication(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                DOWNLOAD_DIR = Environment.getExternalStorageDirectory().getAbsolutePath()
                        + File.separator + StubApplication.getApplication().getPackageName() + File.separator + "download" + File.separator;
            } else {
                DOWNLOAD_DIR = StubApplication.getApplication().getCacheDir().getAbsolutePath() + File.separator + "download" + File.separator;
            }
            return DOWNLOAD_DIR + fileName;
        }
        return "";
    }

    /**
     * 开始下载
     *
     * @param downloadType
     * @param versionData
     */
    public void startDownload(String downloadType, ResponseVersionData versionData) {
        FileDownloader downloader = getFileDownloader(downloadType);
        String updateUrl = versionData.getUpdateUrl();

        if (!TextUtils.isEmpty(updateUrl)) {
            downloader.download(updateUrl, buildFilePath(versionData), this);
        }
    }

    /**
     * 停止下载
     *
     * @param downloadType
     */
    public void stopDownload(String downloadType) {
        FileDownloader downloader = downloaderMap.get(downloadType);
        if (downloader != null) {
            downloader.setIntercept(true);
        }
    }

    public boolean isDownloading(String downloadType) {
        FileDownloader downloader = downloaderMap.get(downloadType);
        if (downloader != null) {
            return downloader.isDownloading();
        }
        return false;
    }

    public int getDownloadedSize(String downloadType, ResponseVersionData versionData) {
        FileDownloader downloader = getFileDownloader(downloadType);
        return (int) downloader.getTemFileSize(buildFilePath(versionData));
    }

    public void syncDownloadInfo(String downloadType) {
        FileDownloader downloader = getFileDownloader(downloadType);
        if (downloader != null) {
            downloader.syncDownloadInfo();
        }
    }

    public boolean isAlreadyDownloadSuccess(String downloadType, ResponseVersionData versionData) {
        String filePath = buildFilePath(versionData);
        File file = new File(filePath);
        return file.exists();

        //验证MD5费时间，发送设备时再验证
//        if (!file.exists()) {
//            return false;
//        }
//        String fileMD5 = "";
//        try {
//            fileMD5 = MD5Util.getFileMD5String(file);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return fileMD5.equalsIgnoreCase(versionData.getMd5Code());
    }

    /**
     * 校验下载文件的md5
     *
     * @param downloadType
     * @param versionData
     * @return
     */
    public boolean checkDownloadFileMD5(String downloadType, ResponseVersionData versionData) {
        String filePath = buildFilePath(versionData);
        File file = new File(filePath);
        if (file.exists()) {
            String fileMD5 = EncryptUtils.encryptMD5File2String(file);
            return fileMD5.equalsIgnoreCase(versionData.getMd5Code());
        }
        return false;
    }

    @Override
    public void onDownloadSuccess(String flagType, FileDownloader downloader, File file) {
        createMainThreadDisposable(t -> {
            for (DownloadObserver observer : obs) {
                observer.onDownloadSuccess(flagType, downloader, file);
            }
        });
    }

    @Override
    public void onDownloading(String flagType, FileDownloader downloader, int progress, int total, int precent) {
        createMainThreadDisposable(t -> {
            for (DownloadObserver observer : obs) {
                observer.onDownloading(flagType, downloader, progress, total, precent);
            }
        });
    }

    @Override
    public void onDownloadStart(String flagType, FileDownloader downloader, int fileSize) {
        createMainThreadDisposable(t -> {
            for (DownloadObserver observer : obs) {
                observer.onDownloadStart(flagType, downloader, fileSize);
            }
        });
    }

    @Override
    public void onDownloadFailed(String flagType, FileDownloader downloader, String msg) {
        createMainThreadDisposable(t -> {
            for (DownloadObserver observer : obs) {
                observer.onDownloadFailed(flagType, downloader, msg);
            }
        });
    }

    @Override
    public void onDownloadSpeed(String flagType, FileDownloader downloader, float speed, int remainedTime) {
        createMainThreadDisposable(t -> {
            for (DownloadObserver observer : obs) {
                observer.onDownloadSpeed(flagType, downloader, speed, remainedTime);
            }
        });
    }

    @Override
    public void onDownloadCancel(String flagType, FileDownloader downloader) {
        createMainThreadDisposable(t -> {
            for (DownloadObserver observer : obs) {
                observer.onDownloadCancel(flagType, downloader);
            }
        });
    }
}